#include "faultapi.hpp"
#include "threados.hpp"
#include "method.hpp"

using namespace motion;

typedef enum
{
	MOTOR_RUNSTATE_STOP = 0,
	MOTOR_RUNSTATE_START,
	MOTOR_RUNSTATE_RUNNING,
}MotorRunStateTPDF;
///>长延时和短延时故障类
fault_iit *mFault_LongDelayCurrent;			///<长延时
fault_big *mFault_ShortDelay;						///<短延时
fault_big *mFault_Earth;								///<接地
fault_iit *mFault_N_LongDelayCurrent;		///<N相长延时
fault_big *mFault_N_ShortDelay;					///<N相短延时
fault_unbalance *mFault_Unbalance;			///<不平衡
fault_big *mFault_BlockCurrent;					///<堵转

static void FaultUpdateParam(void)
{
	if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_MOTOR)	///<电机型
	{
		if(_COMMON_ATTRIBUTE.bLongDelayEnable)
		{
			/** 720 * 720 * 1000 * Tr * 0.8*/
			mFault_LongDelayCurrent->HeatAccumulation = (uint64_t)(518400 * 800) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);	///<518400
			mFault_LongDelayCurrent->Thermolysis = (uint64_t)(5184 * 8) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime); 
			mFault_LongDelayCurrent->FaultEnable = true;
		}
		else
		{
			mFault_LongDelayCurrent->FaultEnable = false;
			mFault_LongDelayCurrent->Reset();
		}
		/** N相长延时*/
		if(_COMMON_ATTRIBUTE.bNLongDelayEnable)
		{
			mFault_N_LongDelayCurrent->HeatAccumulation = (uint64_t)(518400 * 800) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);	///<518400
			mFault_N_LongDelayCurrent->Thermolysis = (uint64_t)(5184 * 8) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);
			mFault_N_LongDelayCurrent->FaultEnable = true;
		}
		else
		{
			mFault_N_LongDelayCurrent->FaultEnable = false;
			mFault_N_LongDelayCurrent->Reset();
		}
	}
	else
	{
		if(_COMMON_ATTRIBUTE.bLongDelayEnable)
		{
			/**长延时 600 * 600 * 1000 * Tr*/
			mFault_LongDelayCurrent->HeatAccumulation = (uint64_t)(360000 * 1000) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);	///<360000
			mFault_LongDelayCurrent->Thermolysis = (uint64_t)(36 * 1000) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);
			mFault_LongDelayCurrent->FaultEnable = true;
		}
		else
		{
			mFault_LongDelayCurrent->FaultEnable = false;
			mFault_LongDelayCurrent->Reset();
		}
		/** N相长延时*/
		if(_COMMON_ATTRIBUTE.bNLongDelayEnable)
		{
			mFault_N_LongDelayCurrent->HeatAccumulation = (uint64_t)(360000 * 1000) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);	///<360000
			mFault_N_LongDelayCurrent->Thermolysis = (uint64_t)(36 * 1000) * (uint64_t)(_COMMON_ATTRIBUTE.uiLongDelayTime);
			mFault_N_LongDelayCurrent->FaultEnable = true;
		}
		else
		{
			mFault_N_LongDelayCurrent->FaultEnable = false;
			mFault_N_LongDelayCurrent->Reset();
		}
	}
	/** 短延时*/
	if(_COMMON_ATTRIBUTE.bShortDelayEnable)
	{
		if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_MOTOR)
		{
			mFault_ShortDelay->FaultTrigValue = _COMMON_ATTRIBUTE.uiShortDelayCurrent;
			mFault_ShortDelay->FaultResumeValue = _COMMON_ATTRIBUTE.uiIr * 90 / 100;
		}
		else
		{
			mFault_ShortDelay->FaultTrigValue = _COMMON_ATTRIBUTE.uiShortDelayCurrent;
			mFault_ShortDelay->FaultResumeValue = _COMMON_ATTRIBUTE.uiIr * 85 / 100;
		}
		mFault_ShortDelay->FaultTrigTime = _COMMON_ATTRIBUTE.uiShortDelayTime * FAULT_TIMEMULT - FAULT_TIME_ADVANCE;
		mFault_ShortDelay->FaultResumeTime = FAULT_RESUMETIME * FAULT_TIMEMULT;
		mFault_ShortDelay->FaultEnable = true;
	}
	else
	{
		mFault_ShortDelay->FaultEnable = false;
		mFault_ShortDelay->Reset();
	}
	/** N相短延时*/
	if(_COMMON_ATTRIBUTE.bNShortDelayEnable)
	{
		mFault_N_ShortDelay->FaultTrigValue = _COMMON_ATTRIBUTE.uiNShortDelayCurrent;
		mFault_N_ShortDelay->FaultTrigTime = _COMMON_ATTRIBUTE.uiShortDelayTime * FAULT_TIMEMULT - FAULT_TIME_ADVANCE;
		mFault_N_ShortDelay->FaultResumeValue = _COMMON_ATTRIBUTE.uiNShortDelayCurrent * 85 / 100;
		mFault_N_ShortDelay->FaultResumeTime = FAULT_RESUMETIME * FAULT_TIMEMULT;
		mFault_N_ShortDelay->FaultEnable = true;
	}
	else
	{
		mFault_N_ShortDelay->FaultEnable = false;
		mFault_N_ShortDelay->Reset();
	}
	/** 接地*/
	if(_COMMON_ATTRIBUTE.bEarthEnable)
	{
		mFault_Earth->FaultTrigValue = _COMMON_ATTRIBUTE.uiEarthCurrent;
		mFault_Earth->FaultTrigTime = _COMMON_ATTRIBUTE.uiEarthTime * FAULT_TIMEMULT - FAULT_TIME_ADVANCE - 10;
		mFault_Earth->FaultResumeValue = _COMMON_ATTRIBUTE.uiEarthCurrent * 8 / 10;
		mFault_Earth->FaultResumeTime = FAULT_RESUMETIME * FAULT_TIMEMULT;
		mFault_Earth->FaultEnable = true;
	}
	else
	{
		mFault_Earth->FaultEnable = false;
		mFault_Earth->Reset();
	}
	/** 不平衡*/
	if(_COMMON_ATTRIBUTE.bUnbalanceEnable)
	{
		mFault_Unbalance->FaultTrigValue = _COMMON_ATTRIBUTE.uiUnbalanceRated;
		mFault_Unbalance->FaultTrigTime = _COMMON_ATTRIBUTE.uiUnbalanceTime * 1000 * FAULT_TIMEMULT - FAULT_TIME_ADVANCE - 500;
		mFault_Unbalance->FaultResumeValue = 25;
		mFault_Unbalance->FaultResumeTime = FAULT_RESUMETIME * FAULT_TIMEMULT;
		mFault_Unbalance->FaultEnable = true;
	}
	else
	{
		mFault_Unbalance->FaultEnable = false;
		mFault_Unbalance->Reset();
	}
	/** 堵转*/
	if(_COMMON_ATTRIBUTE.bBlockEnable)
	{
		mFault_BlockCurrent->FaultTrigValue = _COMMON_ATTRIBUTE.uiBlockCurrent;
		mFault_BlockCurrent->FaultTrigTime = _COMMON_ATTRIBUTE.uiBlockTime * 1000 * FAULT_TIMEMULT - FAULT_TIME_ADVANCE - 500;
		mFault_BlockCurrent->FaultResumeValue = _COMMON_ATTRIBUTE.uiBlockCurrent * 85 / 100;
		mFault_BlockCurrent->FaultResumeTime = FAULT_RESUMETIME * FAULT_TIMEMULT;
		mFault_BlockCurrent->FaultEnable = true;
	}
	else
	{
		mFault_BlockCurrent->FaultEnable = false;
		mFault_BlockCurrent->Reset();
	}
}
///> 故障属性实时更新
FaultCheckResultTPDF* FaultUpdateValue(void)
{
	static FaultCheckResultTPDF Ret = {fault::FAULT_STATUS_NONE, fault::FAULT_STATUS_NONE, fault::FAULT_STATUS_NONE,
																		 fault::FAULT_STATUS_NONE, fault::FAULT_STATUS_NONE, fault::FAULT_STATUS_NONE,
																		 fault::FAULT_STATUS_NONE};
	static MotorRunStateTPDF tMotorRunState = MOTOR_RUNSTATE_STOP;
	uint32_t imax = _MAX_CURRENT;			///<最大相电流
	uint32_t imin = _MIN_CURRENT;			///<最小相电流
	uint32_t iavg = _AVG_CURRENT;			///<平均电流
	uint32_t uiErr[3], uiMax;
																		 
	uiErr[0] = _IA > iavg? (_IA - iavg):(iavg - _IA);
	uiErr[1] = _IB > iavg? (_IB - iavg):(iavg - _IB);
	uiErr[2] = _IC > iavg? (_IC - iavg):(iavg - _IC);
	uiMax = _MAX(uiErr[0],uiErr[1],uiErr[2]);
	/** 模拟计算当前电机运行状态*/
	switch(tMotorRunState)
	{
		case MOTOR_RUNSTATE_STOP:
			if(_MAX_CURRENT > ((_COMMON_ATTRIBUTE.uiIr * 7) / 10))
			{
				tMotorRunState = MOTOR_RUNSTATE_START;
			}
			break;
		case MOTOR_RUNSTATE_START:
			if(iavg < _COMMON_ATTRIBUTE.uiIr * 2)
			{
				tMotorRunState = MOTOR_RUNSTATE_RUNNING;
			}
			break;
		case MOTOR_RUNSTATE_RUNNING:
			if(_MAX_CURRENT < (_COMMON_ATTRIBUTE.uiIr /10))
			{
				tMotorRunState = MOTOR_RUNSTATE_STOP;
			}
			break;
	}
	/** 更新故障参数*/
	FaultUpdateParam();
	/** 更新故障状态*/
	if(mFault_LongDelayCurrent->FaultEnable)		///<长延时
	{
		mFault_LongDelayCurrent->ResourceValue[0] = imax * 100 / _COMMON_ATTRIBUTE.uiLongDelayCurrent;
	}
	if(mFault_ShortDelay->FaultEnable)					///<短延时
	{
		mFault_ShortDelay->ResourceValue[0] = _IA;
		mFault_ShortDelay->ResourceValue[1] = _IB;
		mFault_ShortDelay->ResourceValue[2] = _IC;
	}
	if(mFault_Earth->FaultEnable)								///<接地
	{
		mFault_Earth->ResourceValue[0] = _IGND;
	}
	if(mFault_N_LongDelayCurrent->FaultEnable)	///<N相长延时
	{
		mFault_N_LongDelayCurrent->ResourceValue[0] = _IN * 100 / _COMMON_ATTRIBUTE.uiNLongDelayCurrent;
	}
	if(mFault_N_ShortDelay->FaultEnable)				///<N相短延时
	{
		mFault_N_ShortDelay->ResourceValue[0] = _IN;
	}
	if(mFault_Unbalance->FaultEnable)						///<不平衡
	{
		mFault_Unbalance->IsRunning =	tMotorRunState == MOTOR_RUNSTATE_START? false: true;
		if(iavg && (tMotorRunState != MOTOR_RUNSTATE_STOP))
		{
			mFault_Unbalance->ResourceValue[0] = uiMax * 100 / iavg;
		}
		else
		{
			mFault_Unbalance->ResourceValue[0] = 0;
		}
	}
	if(mFault_BlockCurrent->FaultEnable)				//<堵转
	{
		if(tMotorRunState == MOTOR_RUNSTATE_RUNNING)
		{
			mFault_BlockCurrent->ResourceValue[0] = _IA;
			mFault_BlockCurrent->ResourceValue[1] = _IB;
			mFault_BlockCurrent->ResourceValue[2] = _IC;
		}
		else
		{
			mFault_BlockCurrent->ResourceValue[0] = 0;
			mFault_BlockCurrent->ResourceValue[1] = 0;
			mFault_BlockCurrent->ResourceValue[2] = 0;
		}
	}
	/** 获取故障状态*/
	Ret.tLongDelay = mFault_LongDelayCurrent->FaultStatus;
	Ret.tShortDelay = mFault_ShortDelay->FaultStatus;
	Ret.tNLongDelay = mFault_N_LongDelayCurrent->FaultStatus;
	Ret.tNShortDelay = mFault_N_ShortDelay->FaultStatus;
	Ret.tEarth = mFault_Earth->FaultStatus;
	Ret.tBlock = mFault_BlockCurrent->FaultStatus;
	Ret.tUmb = mFault_Unbalance->FaultStatus;
	return(&Ret);
}

void FaultApiInit(void)
{
	mFault_LongDelayCurrent = new fault_iit();
	mFault_LongDelayCurrent->FaultTrigValue = 120;
	mFault_LongDelayCurrent->FaultResumeValue = 105;
	mFault_LongDelayCurrent->FaultTrigCompareMethod = fault::FAULT_COMPAREMETHOD_OR;
	mFault_LongDelayCurrent->FaultResumeCompareMethod = fault::FAULT_COMPAREMETHOD_AND;
	mFault_LongDelayCurrent->ResourceValueLen = 1;
	
	mFault_N_LongDelayCurrent = new fault_iit();
	mFault_N_LongDelayCurrent->FaultTrigValue = 120;
	mFault_N_LongDelayCurrent->FaultResumeValue = 105;
	mFault_N_LongDelayCurrent->FaultTrigCompareMethod = fault::FAULT_COMPAREMETHOD_OR;
	mFault_N_LongDelayCurrent->FaultResumeCompareMethod = fault::FAULT_COMPAREMETHOD_AND;
	mFault_N_LongDelayCurrent->ResourceValueLen = 1;
	
	mFault_ShortDelay = new fault_big();
	mFault_ShortDelay->FaultTrigCompareMethod = fault::FAULT_COMPAREMETHOD_OR;
	mFault_ShortDelay->FaultResumeCompareMethod = fault::FAULT_COMPAREMETHOD_AND;
	mFault_ShortDelay->ResourceValueLen = 3;
	
	mFault_Earth = new fault_big();
	mFault_Earth->FaultTrigCompareMethod = fault::FAULT_COMPAREMETHOD_OR;
	mFault_Earth->FaultResumeCompareMethod = fault::FAULT_COMPAREMETHOD_AND;
	mFault_Earth->ResourceValueLen = 1;
	
	mFault_N_ShortDelay = new fault_big();
	mFault_N_ShortDelay->FaultTrigCompareMethod = fault::FAULT_COMPAREMETHOD_OR;
	mFault_N_ShortDelay->FaultResumeCompareMethod = fault::FAULT_COMPAREMETHOD_AND;
	mFault_N_ShortDelay->ResourceValueLen = 1;
	
	mFault_Unbalance = new fault_unbalance();
	
	mFault_BlockCurrent = new fault_big();
	mFault_BlockCurrent->FaultTrigCompareMethod = fault::FAULT_COMPAREMETHOD_OR;
	mFault_BlockCurrent->FaultResumeCompareMethod = fault::FAULT_COMPAREMETHOD_AND;
	mFault_BlockCurrent->ResourceValueLen = 3;
	
	FaultUpdateParam();
}
